package com.zmn.oms.dubbo.impl.zmn.serviceprovider.order;

import org.apache.dubbo.config.annotation.Service;
import com.google.common.collect.Lists;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.common.utils.validator.ValidateResult;
import com.zmn.common.utils.validator.ValidatorUtil;
import com.zmn.oms.business.interfaces.work.OrderWorkERPQueryBService;
import com.zmn.oms.common.constant.OrderLogConsts;
import com.zmn.oms.common.constant.OrderStatusConsts;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.dubbo.dto.common.work.WorkSharingEstimateDRO;
import com.zmn.oms.dubbo.dto.zmn.order.OrderDRO;
import com.zmn.oms.dubbo.dto.zmn.order.OrderListDetailDRO;
import com.zmn.oms.dubbo.dto.zmn.order.OrderListPageDRO;
import com.zmn.oms.dubbo.dto.zmn.order.serviceprovider.OrderQueryDIO;
import com.zmn.oms.dubbo.dto.zmn.order.serviceprovider.SpOrderDetailDRO;
import com.zmn.oms.dubbo.impl.zmn.order.OrderWorkBaseRemoteService;
import com.zmn.oms.dubbo.interfaces.zmn.serviceprovider.order.ServProviderOrderListReomteService;
import com.zmn.oms.dubbo.utils.DubboConsts;
import com.zmn.oms.model.entity.log.OrderLog;
import com.zmn.oms.model.entity.work.OrderWorkQuery;
import com.zmn.base.oms.common.model.es.orderwork.EsOrderWork;
import com.zmn.oms.model.vo.work.detail.ZsOrderWorkCommissionVO;
import com.zmn.oms.model.vo.work.detail.ZsOrderWorkDetailVO;
import com.zmn.oms.model.vo.work.erp.SharingEstimateVO;
import com.zmn.oms.services.interfaces.remark.OrderRemarkDetailService;
import com.zmn.oms.services.interfaces.remark.OrderRemarkService;
import com.zmn.oms.zmn.aop.SpOrderLogUtils;
import com.zmn.oms.zmn.business.interfaces.work.ZsOrderWorkQueryBService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 类描述：服务商工单相关
 *
 * @author yule
 * @date 2020/7/2 17:59
 */
@Service(loadbalance = "roundrobin", timeout = 5000, retries = 2, version = DubboConsts.INTERFACE_VERSION, validation = "false")
public class ServProviderOrderListReomteServiceImpl extends OrderWorkBaseRemoteService implements ServProviderOrderListReomteService {
    private static final String TAG = "服务商-订单操作";
    @Autowired
    protected ZsOrderWorkQueryBService zsOrderWorkQueryBService;
    @Autowired
    protected OrderRemarkService orderRemarkService;
    @Autowired
    protected OrderRemarkDetailService orderRemarkDetailService;
    @Autowired
    protected OrderWorkERPQueryBService orderWorkERPQueryBService;

    @Override
    public ResponseDTO<OrderListPageDRO> listOrder(OrderQueryDIO queryDIO) {
        logger.info("[{}] 服务商订单列表：{}", TAG, queryDIO);

        ValidateResult validateResult = ValidatorUtil.validator(queryDIO);

        if (!validateResult.isSuccess()) {
            logger.error("[{}] 参数错误：{}", TAG, validateResult.toString());
            return ResponseDTO.fail("提交参数错误：" + validateResult.toString());
        }

        Objects.requireNonNull(queryDIO.getManageCompanyId());

        OrderWorkQuery query = BeanMapper.map(queryDIO, OrderWorkQuery.class);
        query.setManageCompanyIdList(Lists.newArrayList(queryDIO.getManageCompanyId()));
        query.setCompanyIdList(null);
        query.setCompanyId(null);

        query.setDefaultOrder(GlobalConsts.YES);
        query.setOrderField("receiveTime");

        // 是否挂起
        if (Objects.equals(GlobalConsts.YES, queryDIO.getSuspendStatus())) {
            query.setIsDutySuspend(GlobalConsts.YES);
        }

        return super.listOrder(query);
    }

    @Override
    public ResponseDTO<SpOrderDetailDRO> findOrderWorkDetail(Long orderId, Long workId) {
        logger.info("[{}] 查询订单：{}", TAG, orderId, workId);
        try {
            ZsOrderWorkDetailVO orderWorkDetail = zsOrderWorkQueryBService.findOrderWorkDetail(orderId, workId);
            EsOrderWork esOrderWork = orderWorkListBService.findOrderWorkById(workId);
            if (orderWorkDetail != null) {
                List<OrderLog> orderLogList = orderWorkDetail.getLogList();

                // TODO 日志处理逻辑需要优化（当前服务商不允许看到其他服务商日志）
                //  工单日志 新增了服务公司字段 com.zmn.oms.model.entity.log.OrderLog.manageCompanyId 存储
                //  可以去掉此处特殊处理，进而新增DRO接口返回参数，由服务商门户根据此字段主动过滤
                if (!CollectionUtils.isEmpty(orderLogList)) {

                    int assignIndex = -1;
                    for (int i = 0; i < orderLogList.size(); i++) {
                        if (Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_ASSIGN, orderLogList.get(i).getType())) {
                            assignIndex = i;
                            break;
                        }
                    }
                    List<OrderLog> neworderLogList;
                    if (assignIndex != -1) {
                        List<OrderLog> orderLogs = orderLogList.subList(0, assignIndex + 1);
                        neworderLogList = orderLogs.stream().filter(e -> SpOrderLogUtils.SP_ORDER_LOG_TYPE_LIST.contains(e.getType())).collect(Collectors.toList());
                    } else {
                        // 过滤服务商日志
                        neworderLogList = orderLogList.stream().filter(e -> SpOrderLogUtils.SP_ORDER_LOG_TYPE_LIST.contains(e.getType())).collect(Collectors.toList());
                    }

                    // 替换备注名称
                    neworderLogList.forEach((item) -> {
                        if (Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_SERVICE_PROVIDER_REMARK, item.getType())) {
                            item.setTypeName("工单跟进");
                        }
                    });
                    orderWorkDetail.setLogList(neworderLogList);
                }
            }

            SpOrderDetailDRO orderDetailDRO = BeanMapper.map(orderWorkDetail, SpOrderDetailDRO.class);

            // 分润预估相关数据
            SharingEstimateVO sharingEstimate = null;
            try {
                sharingEstimate = orderWorkERPQueryBService.findSharingEstimate(orderId, workId, false, false);
                if (Objects.nonNull(sharingEstimate)) {
                    orderDetailDRO.setSharingEstimate(BeanMapper.map(sharingEstimate, WorkSharingEstimateDRO.class));
                }
            } catch (OmsBaseException e) {
                logger.debug("工单[{}]无法获取分润信息:{}", workId, e.getMessage());
            }

            orderDetailDRO.setWorkId(workId);

            // 服务商提留
            if (orderWorkDetail.getCommission() != null) {
                ZsOrderWorkCommissionVO commissionVO = orderWorkDetail.getCommission();
                Integer commissionAmount = this.getCommissionAmount(commissionVO);
                orderDetailDRO.setServiceProviderAmount(commissionAmount);
            }

            // 服务商结算金额
            orderDetailDRO.setSpStatementAmount(esOrderWork.getSpStatementAmount());

            // 挂起原因
            orderDetailDRO.setSuspendContent(orderWorkDetail.getDutyFailContent());

            // 处理预约超时
            convertDutyTimeOut(orderDetailDRO, orderWorkDetail);
            // 处理超时
            OrderListDetailDRO orderListDetailDRO = new OrderListDetailDRO();
            processTimeOut(orderListDetailDRO,esOrderWork);
            orderDetailDRO.setPreDutyTimeOut(orderListDetailDRO.getPreDutyTimeOut());
            orderDetailDRO.setPreVisitTimeOut(orderListDetailDRO.getPreVisitTimeOut());
            orderDetailDRO.setAlreadyPreDutyTimeOut(orderListDetailDRO.getAlreadyPreDutyTimeOut());
            orderDetailDRO.setAlreadyPreVisitTimeOut(orderListDetailDRO.getAlreadyPreVisitTimeOut());
            orderDetailDRO.setSuspendStatus(Objects.nonNull(esOrderWork.getSuspendTime()) ? GlobalConsts.YES : GlobalConsts.NO);
            return ResponseDTO.success(orderDetailDRO, "OK");

        } catch (Exception e) {
            e.printStackTrace();
            logger.error("[{}] 订单查询错误：{}", TAG, e);
            return ResponseDTO.fail(e.getMessage());
        }
    }

    @Override
    public ResponseDTO<OrderDRO> getOrderById(Long orderId, Long workId) {
        return super.getOrderById(orderId, workId);
    }

    /**
     * 服务商提留
     *
     * @param acountVO
     * @return
     */
    private Integer getCommissionAmount(ZsOrderWorkCommissionVO acountVO) {
        //计算提成金额
//        Integer commissionAmount = Optional.ofNullable(acountVO.getServiceProviderRetention()).orElse(0)
//                - Optional.ofNullable(acountVO.getInsurance()).orElse(0)
//                - Optional.ofNullable(acountVO.getHelpEach()).orElse(0)
//                - Optional.ofNullable(acountVO.getDeposit()).orElse(0)
//                - Optional.ofNullable(acountVO.getVoucherShare()).orElse(0)
//                - Optional.ofNullable(acountVO.getDiscountShare()).orElse(0)
//                - Optional.ofNullable(acountVO.getIntegralShare()).orElse(0);
        return acountVO.getSpReserveAmount();
    }

    /**
     * 预约时间
     *
     * @param dro
     * @param orderWorkDetailVO
     */
    // 预约超时：下单两小时未预约上门时间且工单状态处于“已录入、已确认、已分单、已派单、已领单”且订单为进行中
    private void convertDutyTimeOut(SpOrderDetailDRO dro, ZsOrderWorkDetailVO orderWorkDetailVO) {

        // 结果-进行中，已派单、已上门可操作
        List<Integer> supportStatusList = Lists.newArrayList(
                OrderStatusConsts.WORK_STATUS_INPUT,
                OrderStatusConsts.WORK_STATUS_CONFIRM,
                OrderStatusConsts.WORK_STATUS_ASSIGN,
                OrderStatusConsts.WORK_STATUS_DISTRIBUTE,
                OrderStatusConsts.WORK_STATUS_TAKE);

        List<Integer> supportResultStatusList = Lists.newArrayList(OrderStatusConsts.WORK_RESULT_DOING);
        boolean resultStatusSupport = supportResultStatusList.contains(orderWorkDetailVO.getResultStatus());
        boolean statusSupport = supportStatusList.contains(orderWorkDetailVO.getStatus());

        boolean isTimeout = DateUtil.addSecond(orderWorkDetailVO.getReceiveTime(), 2 * 60 * 60).before(DateUtil.getNow());

        boolean isNotExistDutyTime = Objects.isNull(orderWorkDetailVO.getDutyTime());
        if (resultStatusSupport && statusSupport && isTimeout && isNotExistDutyTime) {
            dro.setDutyTimeIsTimeout(true);
        }
    }
}
